/**
 * DOM 操作工具函数
 * 提供安全的 DOM 操作方法，避免在热模块替换时出现错误
 */

/**
 * 安全地下载文件
 * @param url 文件URL
 * @param filename 文件名
 * @param mimeType MIME类型
 */
export const safeDownloadFile = (
  url: string, 
  filename: string, 
  mimeType: string = 'application/octet-stream'
): void => {
  try {
    // 创建下载链接
    const link = document.createElement('a');
    link.href = url;
    link.download = filename;
    link.style.display = 'none';
    
    // 使用更安全的DOM操作方式
    try {
      document.body.appendChild(link);
      link.click();
    } finally {
      // 确保清理DOM，即使出现错误也要清理
      try {
        if (document.body.contains(link)) {
          document.body.removeChild(link);
        }
      } catch (cleanupError) {
        console.warn('清理下载链接时出现警告:', cleanupError);
      }
    }
  } catch (error) {
    console.error('下载文件时出错:', error);
    throw error;
  }
};

/**
 * 安全地下载图片
 * @param imageUrl 图片URL
 * @param filename 文件名（可选，会自动生成）
 */
export const safeDownloadImage = (imageUrl: string, filename?: string): void => {
  if (!imageUrl) {
    throw new Error('图片URL不能为空');
  }

  // 生成文件名
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
  const randomNum = Math.floor(Math.random() * 1000);
  const defaultFilename = `image-${timestamp}-${randomNum}.png`;
  
  safeDownloadFile(imageUrl, filename || defaultFilename, 'image/png');
};

/**
 * 安全地移除DOM元素
 * @param element 要移除的元素
 * @param parent 父元素（可选，默认为document.body）
 */
export const safeRemoveElement = (
  element: HTMLElement, 
  parent: HTMLElement = document.body
): void => {
  try {
    if (parent.contains(element)) {
      parent.removeChild(element);
    }
  } catch (error) {
    console.warn('移除DOM元素时出现警告:', error);
  }
};

/**
 * 安全地添加DOM元素
 * @param element 要添加的元素
 * @param parent 父元素（可选，默认为document.body）
 */
export const safeAppendElement = (
  element: HTMLElement, 
  parent: HTMLElement = document.body
): void => {
  try {
    parent.appendChild(element);
  } catch (error) {
    console.error('添加DOM元素时出错:', error);
    throw error;
  }
}; 

/**
 * 安全解析JSON响应，处理HTML错误页面
 * @param response - Fetch API响应对象
 * @returns 解析后的JSON数据
 */
export async function safeJsonParse(response: Response): Promise<any> {
  try {
    const text = await response.text();
    
    // 检查是否返回了HTML而不是JSON
    if (text.trim().startsWith('<!DOCTYPE') || text.trim().startsWith('<html')) {
      throw new Error(`服务器返回了HTML页面而不是JSON: ${response.status} ${response.statusText}`);
    }
    
    // 尝试解析JSON
    return JSON.parse(text);
  } catch (error) {
    if (error instanceof SyntaxError) {
      throw new Error(`JSON解析失败: ${error.message}`);
    }
    throw error;
  }
}

/**
 * 检查响应是否为成功的JSON响应
 * @param response - Fetch API响应对象
 * @returns 是否为成功的JSON响应
 */
export function isJsonResponse(response: Response): boolean {
  const contentType = response.headers.get('content-type');
  return Boolean(contentType && contentType.includes('application/json'));
}

/**
 * 处理API响应，自动处理JSON和错误
 * @param response - Fetch API响应对象
 * @returns 解析后的数据
 */
export async function handleApiResponse(response: Response): Promise<any> {
  if (!response.ok) {
    // 如果是JSON错误响应
    if (isJsonResponse(response)) {
      const errorData = await response.json();
      throw new Error(errorData.error || `HTTP ${response.status}: ${response.statusText}`);
    }
    
    // 如果是HTML错误页面
    const text = await response.text();
    if (text.trim().startsWith('<!DOCTYPE') || text.trim().startsWith('<html')) {
      throw new Error(`服务器错误 ${response.status}: ${response.statusText}`);
    }
    
    throw new Error(`请求失败 ${response.status}: ${response.statusText}`);
  }
  
  // 成功响应，解析JSON
  return await safeJsonParse(response);
} 